Imports Microsoft.VisualBasic
Imports System.Data
Imports System.Data.SqlClient
Imports System.Collections.Generic

Namespace Wrox.Commerce

    ''' <summary>
    ''' Shopping cart item
    ''' </summary>
    ''' <remarks>Stores a single item in the shopping cart</remarks>
    <Serializable()> _
    Public Class CartItem

#Region "Private Member Variables"

        ' private member variables: the private storage for the properties
        Private _productID As Integer
        Private _productName As String
        Private _productImageUrl As String
        Private _quantity As Integer
        Private _price As Double
        Private _lineTotal As Double

#End Region

#Region "Constructors"

        ''' <summary>
        ''' Create a new cart item
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub New()
            ' no initialization
        End Sub

        ''' <summary>
        ''' Create a new cart item with the supplied values
        ''' </summary>
        ''' <param name="ProductID">The <see cref="System.Integer">product ID</see></param>
        ''' <param name="ProductName">The <see cref="System.String">product name</see></param>
        ''' <param name="ProductImageUrl">The <see cref="System.String">URL of the product image</see></param>
        ''' <param name="Quantity">The <see cref="System.Integer">quantity required</see></param>
        ''' <param name="Price">The <see cref="System.Double">price of the product</see></param>
        ''' <remarks></remarks>
        Public Sub New(ByVal ProductID As Integer, ByVal ProductName As String, ByVal ProductImageUrl As String, ByVal Quantity As Integer, ByVal Price As Double)

            ' initialize the private member variables with the supplied values
            _productID = ProductID
            _productName = ProductName
            _productImageUrl = ProductImageUrl
            _quantity = Quantity
            _price = Price
            _lineTotal = Quantity * Price

        End Sub

#End Region

#Region "Properties"
        ''' <summary>
        ''' Product ID
        ''' </summary>
        ''' <value></value>
        ''' <remarks></remarks>
        Public Property ProductID() As Integer
            Get
                Return _productID
            End Get
            Set(ByVal value As Integer)
                _productID = value
            End Set
        End Property

        ''' <summary>
        ''' Product name
        ''' </summary>
        ''' <value></value>
        ''' <remarks></remarks>
        Public Property ProductName() As String
            Get
                Return _productName
            End Get
            Set(ByVal value As String)
                _productName = value
            End Set
        End Property

        ''' <summary>
        ''' URL of the product image
        ''' </summary>
        ''' <value></value>
        ''' <remarks></remarks>
        Public Property ProductImageUrl() As String
            Get
                Return _productImageUrl
            End Get
            Set(ByVal value As String)
                _productImageUrl = value
            End Set
        End Property

        ''' <summary>
        ''' Quantity required
        ''' </summary>
        ''' <value></value>
        ''' <remarks></remarks>
        Public Property Quantity() As Integer
            Get
                Return _quantity
            End Get
            Set(ByVal value As Integer)
                _quantity = value
            End Set
        End Property

        ''' <summary>
        ''' Product price
        ''' </summary>
        ''' <value></value>
        ''' <remarks></remarks>
        Public Property Price() As Double
            Get
                Return _price
            End Get
            Set(ByVal value As Double)
                _price = value
            End Set
        End Property

        ''' <summary>
        ''' Line total
        ''' </summary>
        ''' <value></value>
        ''' <remarks>Read only</remarks>
        Public ReadOnly Property LineTotal() As Double
            Get
                Return _quantity * _price
            End Get
        End Property
#End Region

    End Class

    ''' <summary>
    ''' The shopping cart
    ''' </summary>
    ''' <remarks></remarks>
    <Serializable()> _
    Public Class ShoppingCart

        ' percentage discount given to members
        Private Const MemberDiscountPercentage As Single = 0.1

#Region "Private Member Variables"

        Private _dateCreated As DateTime
        Private _lastUpdate As DateTime
        Private _items As List(Of CartItem)

#End Region

#Region "Constructors"

        ''' <summary>
        ''' Createa new instance of the cart
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub New()
            If _items Is Nothing Then
                _items = New List(Of CartItem)
                _dateCreated = DateTime.Now
            End If
        End Sub

#End Region

#Region "Properties"
        ''' <summary>
        ''' The items contained within the cart
        ''' </summary>
        ''' <value></value>
        ''' <remarks>Contains a <see cref="System.Collections.Generic.List(Of CartItem)">List</see> of <paramref name="CartItem">CartItem</paramref> objects</remarks>
        Public Property Items() As List(Of CartItem)
            Get
                Return _items
            End Get
            Set(ByVal value As List(Of CartItem))
                _items = value
            End Set
        End Property

        ''' <summary>
        ''' Returns the amount of the member discount 
        ''' </summary>
        ''' <value></value>
        ''' <remarks>0 if the user is not a member. Read only</remarks>
        Public ReadOnly Property MemberDiscount() As Double
            Get
                If HttpContext.Current.User.IsInRole("FanClubMember") Then
                    Return SubTotal * MemberDiscountPercentage
                Else
                    Return 0
                End If
            End Get
        End Property

        ''' <summary>
        ''' Returns the subtotal of the order
        ''' </summary>
        ''' <value></value>
        ''' <remarks>Read only</remarks>
        Public ReadOnly Property SubTotal() As Double
            Get
                Dim t As Double

                If _items Is Nothing Then
                    Return 0
                End If

                For Each Item As CartItem In _items
                    t += Item.LineTotal
                Next

                Return t
            End Get
        End Property

        ''' <summary>
        ''' Returns the total order value, including member discount
        ''' </summary>
        ''' <value></value>
        ''' <remarks></remarks>
        Public ReadOnly Property Total() As Double
            Get
                Return SubTotal - MemberDiscount
            End Get
        End Property

#End Region

#Region "Methods"
        ''' <summary>
        ''' Insert an item into the cart
        ''' </summary>
        ''' <param name="ProductID">The <see cref="System.Integer">product ID</see></param>
        ''' <param name="Price">The <see cref="System.Double">price of the product</see></param>
        ''' <param name="Quantity">The <see cref="System.Integer">quantity required</see></param>
        ''' <param name="ProductName">The <see cref="System.String">product name</see></param>
        ''' <param name="ProductImageUrl">The <see cref="System.String">URL of the product image</see></param>
        ''' <remarks></remarks>
        Public Sub Insert(ByVal ProductID As Integer, ByVal Price As Double, ByVal Quantity As Integer, ByVal ProductName As String, ByVal ProductImageUrl As String)

            ' check to see if the item already exists in the cart
            Dim ItemIndex As Integer = ItemIndexOfID(ProductID)

            ' -1 means the item wasn't in the cart already, so add it
            If ItemIndex = -1 Then
                Dim NewItem As New CartItem()

                NewItem.ProductID = ProductID
                NewItem.Quantity = Quantity
                NewItem.Price = Price
                NewItem.ProductName = ProductName
                NewItem.ProductImageUrl = ProductImageUrl

                _items.Add(NewItem)
            Else
                ' the item already exists, so just increment the quantity
                _items(ItemIndex).Quantity += 1
            End If

            _lastUpdate = DateTime.Now()

        End Sub

        ''' <summary>
        ''' 
        ''' </summary>
        ''' <param name="RowID">The <see cref="System.Integer">row id</see></param>
        ''' <param name="ProductID">The <see cref="System.Integer">product ID</see></param>
        ''' <param name="Quantity">The <see cref="System.Integer">quantity required</see></param>
        ''' <param name="Price">The <see cref="System.Double">price of the product</see></param>
        ''' <remarks></remarks>
        Public Sub Update(ByVal RowID As Integer, ByVal ProductID As Integer, ByVal Quantity As Integer, ByVal Price As Double)

            Dim Item As CartItem = _items(RowID)

            Item.ProductID = ProductID
            Item.Quantity = Quantity
            Item.Price = Price
            _lastUpdate = DateTime.Now()

        End Sub

        ''' <summary>
        ''' Returns the index of the item in the collection
        ''' </summary>
        ''' <param name="ProductID"></param>
        ''' <returns></returns>
        ''' <remarks>-1 if the item isn't found</remarks>
        Private Function ItemIndexOfID(ByVal ProductID As Integer) As Integer

            Dim index As Integer

            For Each item As CartItem In _items
                If item.ProductID = ProductID Then
                    Return index
                End If
                index += 1
            Next

            Return -1

        End Function

        ''' <summary>
        ''' Deletes an item form the cart
        ''' </summary>
        ''' <param name="rowID">The <see cref="System.Integer">row ID of the item to delete</see></param>
        ''' <remarks></remarks>
        Public Sub DeleteItem(ByVal rowID As Integer)

            _items.RemoveAt(rowID)
            _lastUpdate = DateTime.Now()

        End Sub
#End Region

    End Class

End Namespace
